home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr44 / xlib06p1.zip / WXMAIN.CPP < prev    next >
C/C++ Source or Header  |  1995-03-15  |  29KB  |  1,017 lines

  1. #include <conio.h>
  2. #include <dos.h>
  3. #include <mem.h>
  4.  
  5. #include "xstubs.h"
  6. #include "xinternl.h"
  7. /*==================================================================
  8. XMAIN.CPP contains the basic setup variables and functions for the
  9. XLIB package.
  10.  
  11. These routines were written initially by Themie Gouthas and
  12. company and modified March 1995 by Victor B. Putz.
  13. ===================================================================*/
  14.  
  15.  
  16. /*==================================================================
  17. This contains variables that really belong to other functions,
  18. but we'll define them here
  19. ===================================================================*/
  20.  
  21. int VsyncHandlerActive = 0;
  22. int MouseRefreshFlag = 0;
  23. int MouseVsyncHandler = 0;
  24. int WaitingStartLow = 0;
  25. int WaitingStartHigh = 0;
  26. int WaitingPelPan = 0;
  27. int VsyncPaletteStart = 0;
  28. int VsyncPaletteCount = 0;
  29.  
  30.  
  31.  
  32.  
  33. /*==================================================================
  34. This block contains variable declarations for the xlib routines
  35. ===================================================================*/
  36. BYTE InGraphics = 0;             /* non zero if in X graphics mode      */
  37. int CurrXMode = 0;              /* contains current X graphics mode id */
  38. int ScrnPhysicalByteWidth = 0;  /* Physical screen width in bytes      */
  39. xScreenCoord_t ScrnPhysicalPixelWidth = 0; /* Physical screen width in pixels     */
  40. xScreenCoord_t ScrnPhysicalHeight = 0;     /* Physical screen height in pixels    */
  41. int ErrorValue = 0;             /* Error return value                  */
  42. xPageHandle_t SplitScrnOffs = 0;          /* Offset in VRAM  of split screen     */
  43. xScreenCoord_t SplitScrnScanLine = 0;      /* Scan line split screen starts at    */
  44.        /* initially. Resizing the split scrn  */
  45.        /* using the other functions does not  */
  46.        /* change this value                   */
  47. int SplitScrnVisibleHeight = 0; /* Height of the visible portion of the*/
  48.        /* split screen.                       */
  49. xPageHandle_t Page0_Offs = 0;             /* Offset in VRAM of main virt. screen */
  50. xPageHandle_t Page1_Offs = 0;             /* Offset in VRAM of 2nd virt. screen  */
  51. xPageHandle_t Page2_Offs = 0;             /* Offset in VRAM of 3rd virt. screen  */
  52. int ScrnLogicalByteWidth = 0;   /* Virtual screen width in bytes       */
  53. xScreenCoord_t ScrnLogicalPixelWidth = 0;  /* Virtual screen width in pixels      */
  54. xScreenCoord_t ScrnLogicalHeight = 0;      /* Virtual screen height in pixels     */
  55. xScreenCoord_t MaxScrollX = 0;             /* Max X position of physical screen   */
  56.        /*  within virtual screen              */
  57. xScreenCoord_t MaxScrollY = 0;             /* Max Y position of physical screen   */
  58.        /*  within virtual screen              */
  59. int DoubleBufferActive = 0;     /* Indicates whether double buffering  */
  60.          /* is active                           */
  61. int TrippleBufferActive = 0;    /* Indicates whether tripple           */
  62.        /* buffering is active                 */
  63. int VisiblePageIdx = 0;         /* Index number of visible page 0 or 1 */
  64. xPageHandle_t HiddenPageOffs = 0;         /* Offset of Hidden Pg | only valid    */
  65. xPageHandle_t VisiblePageOffs = 0;        /* Offset of Visible Pg| for D.B. mode */
  66. xPageHandle_t WaitingPageOffs = 0;        /* Offset of Waiting Pg| for T.B. mode */
  67. xPageHandle_t NonVisual_Offs = 0;         /* Offset of first non-visible VRAM    */
  68.  
  69. int StartAddressFlag = 0;
  70.  
  71. xScreenCoord_t TopClip = 0;                /* Clipping rectangle                  */
  72. xScreenCoord_t BottomClip = 0;
  73. xScreenCoord_t LeftClip = 0;
  74. xScreenCoord_t RightClip = 0;
  75.  
  76. xScreenCoord_t PhysicalStartPixelX = 0;    /* Coordinates of physical (visible) */
  77. int PhysicalStartByteX = 0;     /* screen relative to the virtual    */
  78. xScreenCoord_t PhysicalStartY = 0;         /* screen's U.L. corner              */
  79.  
  80. unsigned char SplitScrnActive = 0;
  81.  
  82. char VsyncPaletteBuffer[ 768 ];
  83.  
  84. unsigned char * pbVGABuffer = (unsigned char *)(0xA000 << 4);
  85.  
  86. void x_set_start_addr( xScreenCoord_t, xScreenCoord_t );
  87.  
  88. /*
  89. ZeroOutParameters() zeros out all the xlib variables.
  90. */
  91. void ZeroOutParameters(
  92.   void
  93. )
  94. {
  95.   InGraphics = 0;             /* non zero if in X graphics mode      */
  96.   CurrXMode = 0;              /* contains current X graphics mode id */
  97.   ScrnPhysicalByteWidth = 0;  /* Physical screen width in bytes      */
  98.   ScrnPhysicalPixelWidth = 0; /* Physical screen width in pixels     */
  99.   ScrnPhysicalHeight = 0;     /* Physical screen height in pixels    */
  100.   ErrorValue = 0;             /* Error return value                  */
  101.   SplitScrnOffs = 0;          /* Offset in VRAM  of split screen     */
  102.   SplitScrnScanLine = 0;      /* Scan line split screen starts at    */
  103.          /* initially. Resizing the split scrn  */
  104.          /* using the other functions does not  */
  105.          /* change this value                   */
  106.   SplitScrnVisibleHeight = 0; /* Height of the visible portion of the*/
  107.          /* split screen.                       */
  108.   Page0_Offs = 0;             /* Offset in VRAM of main virt. screen */
  109.   Page1_Offs = 0;             /* Offset in VRAM of 2nd virt. screen  */
  110.   Page2_Offs = 0;             /* Offset in VRAM of 3rd virt. screen  */
  111.   ScrnLogicalByteWidth = 0;   /* Virtual screen width in bytes       */
  112.   ScrnLogicalPixelWidth = 0;  /* Virtual screen width in pixels      */
  113.   ScrnLogicalHeight = 0;      /* Virtual screen height in pixels     */
  114.   MaxScrollX = 0;             /* Max X position of physical screen   */
  115.          /*  within virtual screen              */
  116.   MaxScrollY = 0;             /* Max Y position of physical screen   */
  117.          /*  within virtual screen              */
  118.   DoubleBufferActive = 0;     /* Indicates whether double buffering  */
  119.            /* is active                           */
  120.   TrippleBufferActive = 0;    /* Indicates whether tripple           */
  121.          /* buffering is active                 */
  122.   VisiblePageIdx = 0;         /* Index number of visible page 0 or 1 */
  123.   HiddenPageOffs = 0;         /* Offset of Hidden Pg | only valid    */
  124.   VisiblePageOffs = 0;        /* Offset of Visible Pg| for D.B. mode */
  125.   WaitingPageOffs = 0;        /* Offset of Waiting Pg| for T.B. mode */
  126.   NonVisual_Offs = 0;         /* Offset of first non-visible VRAM    */
  127.  
  128.   StartAddressFlag = 0;
  129.  
  130.   TopClip = 0;                /* Clipping rectangle                  */
  131.   BottomClip = 0;
  132.   LeftClip = 0;
  133.   RightClip = 0;
  134.  
  135.   PhysicalStartPixelX = 0;    /* Coordinates of physical (visible) */
  136.   PhysicalStartByteX = 0;     /* screen relative to the virtual    */
  137.   PhysicalStartY = 0;         /* screen's U.L. corner              */
  138.  
  139.   for ( int i = 0; i < 768; ++i ) {
  140.     VsyncPaletteBuffer[ i ] = 0;
  141.   }
  142. }
  143.  
  144. BYTE PelPanMask[  ] = {
  145.   0x00,
  146.   0x02,
  147.   0x04,
  148.   0x06
  149. };
  150.  
  151. BYTE DoubleScanFlag = 0;
  152.  
  153. inline void WaitVsyncStart(
  154.   void
  155. )
  156. {
  157.   while( inp( INPUT_STATUS_0 ) & 0x08 );
  158.   while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
  159. }
  160.  
  161. /*==================================================================
  162. The following sets of arrays are the register parameters to set up
  163. the various x modes.
  164. ===================================================================*/
  165. struct XSetup_t {
  166.   int iWidth;
  167.   int iHeight;
  168.   int iDotClock;
  169.   int iNumRegisters;
  170.   int aiRegisterValues[];
  171. };
  172.  
  173. XSetup_t X256Y200 = {
  174.   256,
  175.   200,
  176.   0x0e3,
  177.   8,
  178.   {
  179.     0x5f00,   //horz total
  180.     0x3f01,   //horz displayed
  181.     0x4202,   //start horz blanking
  182.     0x9f03,   //end horz blanking
  183.     0x4c04,   //start h sync
  184.     0x0005,   //end h sync
  185.     0x0014,   //turn off dword mode
  186.     0xe317   //turn on byte mode
  187.   }
  188. };
  189.  
  190. XSetup_t X256Y240 = {
  191.   256,
  192.   240,
  193.   0x0e3,
  194.   16,
  195.   {
  196.     0x5f00,  //horz total
  197.     0x3f01,  //horz displayed
  198.     0x4202,  //start horz blanking
  199.     0x9f03,  //end horz blanking
  200.     0x4c04,  //start h sync
  201.     0x0005,  //end h sync
  202.     0x0d06,  //vertical total
  203.     0x3e07,  //overflow (bit 8 of vertical counts)
  204.     0x4109,  //cell height (2 to double-scan)
  205.     0xea10,  //v sync start
  206.     0xac11,  //v sync end and protect cr0-cr7
  207.     0xdf12,  //vertical displayed
  208.     0x0014,  //turn off dword mode
  209.     0xe715,  //v blank start
  210.     0x0616,  //v blank end
  211.     0xe317   //turn on byte mode
  212.   }
  213. };
  214.  
  215. XSetup_t X320Y200 = {
  216.   320,
  217.   200,
  218.   0,
  219.   2,
  220.   {
  221.     0x0014, //Turn off dword mode
  222.     0xe317  //Turn on byte mode
  223.   }
  224. };
  225.  
  226. XSetup_t X320Y240 = {
  227.   320,
  228.   240,
  229.   0x0e3,
  230.   10,
  231.   {
  232.     0x0d06,  //vertical total
  233.     0x3e07,  //overflow (bit 8 of vertical counts)
  234.     0x4109,  //cell height (2 to double-scan)
  235.     0xea10,  //v sync start
  236.     0xac11,  //v sync end and protect cr0-cr7
  237.     0xdf12,  //vertical displayed
  238.     0x0014,  //turn off dword mode
  239.     0xe715,  //v blank start
  240.     0x0616,  //v blank end
  241.     0xe317   //turn on byte mode
  242.   }
  243. };
  244.  
  245. XSetup_t X360Y200 = {
  246.   360,
  247.   200,
  248.   0x0e7,
  249.   8,
  250.   {
  251.     0x6b00,  //horz total
  252.     0x5901,  //horz displayed
  253.     0x5a02,  //start horz blanking
  254.     0x8e03,  //end horz blanking
  255.     0x5e04,  //start h sync
  256.     0x8a05,  //end h sync
  257.     0x0014,  //turn off dword mode
  258.     0xe317   //turn on byte mode
  259.   }
  260. };    
  261.   
  262. XSetup_t X360Y240 = {
  263.   360,
  264.   240,
  265.   0x0e7,
  266.   17,
  267.   {
  268.     0x6b00,  //horz total
  269.     0x5901,  //horz displayed
  270.     0x5a02,  //start horz blanking
  271.     0x8e03,  //end horz blanking
  272.     0x5e04,  //start h sync
  273.     0x8a05,  //end h sync
  274.     0x0d06,  //vertical total
  275.     0x3e07,  //overflow (bit 8 of vertical counts)
  276.     0x4109,  //cell height (2 to double-scan)
  277.     0xea10,  //v sync start
  278.     0xac11,  //v sync end and protect cr0-cr7
  279.     0xdf12,  //vertical displayed
  280.     0x2d13,  //offset;
  281.     0x0014,  //turn off dword mode
  282.     0xe715,  //v blank start
  283.     0x0616,  //v blank end
  284.     0xe317   //turn on byte mode
  285.   }
  286. };
  287.  
  288.     
  289. XSetup_t X376Y282 = {
  290.   376,
  291.   282,
  292.   0x0e7,
  293.   18,
  294.   {
  295.     0x6e00,  //horz total
  296.     0x5d01,  //horz displayed
  297.     0x5e02,  //start horz blanking
  298.     0x9103,  //end horz blanking
  299.     0x6204,  //start h sync
  300.     0x8f05,  //end h sync
  301.     0x6206,  //vertical total
  302.     0xf007,  //overflow
  303.     0x6109,  //cell height
  304.     0x310f,  //Unknown?-->VPutz
  305.     0x3710,  //v sync start
  306.     0x8911,  //v sync end and protect cr0-cr7
  307.     0x3312,  //vertical displayed
  308.     0x2f13,  //offset
  309.     0x0014,  //turn off dword mode
  310.     0x3c15,  //v blank start
  311.     0x5c16,  //v blank end
  312.     0xe317  //turn on byte mode
  313.   }
  314. };
  315.  
  316. XSetup_t X256Y400 = {
  317.   256,
  318.   400,
  319.   0x0e3,
  320.   8,
  321.   {
  322.     0x5f00,  //horz total
  323.     0x3f01,  //horz displayed
  324.     0x4202,  //start horz blanking
  325.     0x9f03,  //end horz blanking
  326.     0x4c04,  //start h sync
  327.     0x0005,  //end h sync
  328.     0x4009,  //cell height
  329.     0x0014,  //turn off dword mode
  330.     0xe317   //turn on byte mode
  331.   }
  332. };
  333.  
  334. XSetup_t X256Y480 = {
  335.   256,
  336.   480,
  337.   0x0e3,
  338.   16,
  339.   {
  340.     0x5f00,  //horz total
  341.     0x3f01,  //horz displayed
  342.     0x4202,  //start horz blanking
  343.     0x9f03,  //end horz blanking
  344.     0x4c04,  //start h sync
  345.     0x0005,  //end h sync
  346.     0x0d06,  //vertical total
  347.     0x3e07,  //overflow (bit 8 of vertical counts)
  348.     0x4009,  //cell height (2 to double-scan)
  349.     0xea10,  //v sync start
  350.     0xac11,  //v sync end and protect cr0-cr7
  351.     0xdf12,  //vertical displayed
  352.     0x0014,  //turn off dword mode
  353.     0xe715,  //v blank start
  354.     0x0616,  //v blank end
  355.     0xe317   //turn on byte mode
  356.   }
  357. };
  358.  
  359.  
  360. XSetup_t X320Y400 = {
  361.   320,
  362.   400,
  363.   0x0e3,
  364.   3,
  365.   {
  366.     0x4009,  //cell height
  367.     0x0014,  //turn off dword mode
  368.     0xe317   //turn on byte mode
  369.   }
  370. };
  371.  
  372. XSetup_t X320Y480 = {
  373.   320,
  374.   480,
  375.   0x0e3,
  376.   10,
  377.   {
  378.     0x0d06,  //vertical total
  379.     0x3e07,  //overflow (bit 8 of vertical counts)
  380.     0x4009,  //cell height (2 to double-scan)
  381.     0xea10,  //v sync start
  382.     0xac11,  //v sync end and protect cr0-cr7
  383.     0xdf12,  //vertical displayed
  384.     0x0014,  //turn off dword mode
  385.     0xe715,  //v blank start
  386.     0x0616,  //v blank end
  387.     0xe317   //turn on byte mode
  388.   }
  389. };
  390.  
  391. XSetup_t X360Y400 = {
  392.   360,
  393.   400,
  394.   0x0e7,
  395.   9,
  396.   {
  397.     0x6b00,  //horz total
  398.     0x5901,  //horz displayed
  399.     0x5a02,  //start horz blanking
  400.     0x8e03,  //end horz blanking
  401.     0x5e04,  //start h sync
  402.     0x8a05,  //end h sync
  403.     0x4009,  //cell height
  404.     0x0014,  //turn off dword mode
  405.     0xe317   //turn on byte mode
  406.   }
  407. };
  408.  
  409. XSetup_t X360Y480 = {
  410.   360,
  411.   480,
  412.   0x0e7,
  413.   17,
  414.   {
  415.     0x6b00,  //horz total
  416.     0x5901,  //horz displayed
  417.     0x5a02,  //start horz blanking
  418.     0x8e03,  //end horz blanking
  419.     0x5e04,  //start h sync
  420.     0x8a05,  //end h sync
  421.     0x0d06,  //vertical total
  422.     0x3e07,  //overflow
  423.     0x4009,  //cell height
  424.     0xea10,  //v sync start
  425.     0xac11,  //v sync end and protect cr0-cr7
  426.     0xdf12,  //vertical displayed
  427.     0x2d13,  //offset
  428.     0x0014,  //turn off dword mode
  429.     0xe715,  //v blank start
  430.     0x0616,  //v blank end
  431.     0xe317   //turn on byte mode
  432.   }
  433. };
  434.  
  435. XSetup_t X360Y360 = {
  436.   360,
  437.   360,
  438.   0x0e7,
  439.   15,
  440.   {
  441.     0x6b00,  //horz total
  442.     0x5901,  //horz displayed
  443.     0x5a02,  //start horz blanking
  444.     0x8e03,  //end horz blanking
  445.     0x5e04,  //start h sync
  446.     0x8a05,  //end h sync
  447.     0x4009,  //cell height
  448.     0x8810,  //v sync start
  449.     0x8511,  //v sync end and protect cr0-cr7
  450.     0x6712,  //vertical displayed
  451.     0x2d13,  //offset
  452.     0x0014,  //turn off dword mode
  453.     0x6d15,  //v blank start
  454.     0xba16,  //v blank end
  455.     0xe317   //turn on byte mode
  456.   }
  457. };
  458.  
  459. XSetup_t X376Y308 = {
  460.   376,
  461.   308,
  462.   0x0e7,
  463.   18,
  464.   {
  465.     0x6e00,  //horz total
  466.     0x5d01,  //horz displayed
  467.     0x5e02,  //start horz blanking
  468.     0x9103,  //end horz blanking
  469.     0x6204,  //start h sync
  470.     0x8f05,  //end h sync
  471.     0x6206,  //vertical total
  472.     0x0f07,  //overflow
  473.     0x4009,  //Unknown?-->VPutz
  474.     0x310f,  //Unknown?-->VPutz
  475.     0x3710,  //v sync start
  476.     0x8911,  //v sync end and protect cr0-cr7
  477.     0x3312,  //vertical displayed
  478.     0x2f13,  //offset
  479.     0x0014,  //turn off dword mode
  480.     0x3c15,  //v blank start
  481.     0x5c16,  //v blank end
  482.     0xe317   //turn on byte mode
  483.   }
  484. };
  485.  
  486. XSetup_t X376Y564 = {
  487.   376,
  488.   564,
  489.   0x0e7,
  490.   18,
  491.   {
  492.     0x6e00,  //horz total
  493.     0x5d01,  //horz displayed
  494.     0x5e02,  //start horz blanking
  495.     0x9103,  //end horz blanking
  496.     0x6204,  //start h sync
  497.     0x8f05,  //end h sync
  498.     0x6206,  //vertical total
  499.     0xf007,  //overflow
  500.     0x6009,  //Unknown?-->VPutz
  501.     0x310f,  //Unknown?-->VPutz
  502.     0x3710,  //v sync start
  503.     0x8911,  //v sync end and protect cr0-cr7
  504.     0x3312,  //vertical displayed
  505.     0x2f13,  //offset
  506.     0x0014,  //turn off dword mode
  507.     0x3c15,  //v blank start
  508.     0x5c16,  //v blank end
  509.     0xe317   //turn on byte mode
  510.   }
  511. };
  512.     
  513. XSetup_t * apSetupTable[] = {
  514.   &X320Y200,
  515.   &X320Y240,
  516.   &X360Y200,
  517.   &X360Y240,
  518.   &X376Y282,
  519.   &X320Y400,
  520.   &X320Y480,
  521.   &X360Y400,
  522.   &X360Y480,
  523.   &X360Y360,
  524.   &X376Y308,
  525.   &X376Y564,
  526.   &X256Y200,
  527.   &X256Y240
  528. };  
  529.  
  530.  
  531. /*==================================================================
  532. Now begins the actual "mock xlib" routines.
  533. ===================================================================*/
  534.  
  535. /*
  536. SetLogicalScreenWidth() sets the logical page width.
  537. */
  538. void SetLogicalScreenWidth(
  539.   xScreenCoord_t iNewLogicalWidth
  540. )
  541. {
  542.     //first round to the last multiple of 8
  543.     iNewLogicalWidth &= ( ~0x0f );
  544.   outp( CRTC_INDEX, CRTC_OFFSET );
  545.   if ( iNewLogicalWidth < ScrnPhysicalPixelWidth ) {
  546.     iNewLogicalWidth = ScrnPhysicalPixelWidth;
  547.   }
  548.   outp( CRTC_INDEX + 1, iNewLogicalWidth / 8 );
  549.   ScrnLogicalByteWidth = iNewLogicalWidth / 4;
  550.   RightClip = iNewLogicalWidth / 4;
  551.   MaxScrollX = iNewLogicalWidth - ( iNewLogicalWidth / 4 - ScrnPhysicalByteWidth ) * 4;
  552.   ScrnLogicalPixelWidth = iNewLogicalWidth;
  553.   ScrnLogicalHeight = ( 0xffff / ScrnLogicalByteWidth );
  554.   BottomClip = ScrnLogicalHeight;
  555.   MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight;
  556.   NonVisual_Offs = ScrnLogicalByteWidth * ScrnPhysicalHeight;
  557. }
  558.  
  559. /*
  560. ClearVideoMemory() zeros all video memory by selecting all
  561. planes and writing zero to the whole segment.
  562. */
  563. void ClearVideoMemory(
  564.   void
  565. )
  566. {
  567.   outpw(SC_INDEX, ALL_PLANES);
  568.   memset( pbVGABuffer, 0x0, 0x10000);
  569. }
  570.  
  571. #define LAST_X_MODE 13
  572. /*
  573. x_set_mode() sets the valid graphics mode.
  574. */
  575. int x_set_mode(
  576.   int iGraphicsMode,
  577.   xScreenCoord_t iNewLogicalWidth
  578. )
  579. {
  580.   ZeroOutParameters();
  581.   //if we've selected an invalid mode, exit
  582.   if ( LAST_X_MODE <= iGraphicsMode ) {
  583.     InGraphics = FALSE;
  584.     return -1;
  585.   }
  586.   //set the current graphics mode flags
  587.   CurrXMode = iGraphicsMode;
  588.   InGraphics = TRUE;
  589.   if ( iGraphicsMode <= 3 ) {
  590.     DoubleScanFlag = TRUE;
  591.   }
  592.   else {
  593.     DoubleScanFlag = FALSE;
  594.   }
  595.   ClearVideoMemory();
  596.   //set base x mode
  597.   union REGS r;
  598.   r.x.eax = 0x0013;
  599.   int386(0x10, &r, &r);
  600.   outpw( SC_INDEX, 0x0604 );
  601.   outpw( SC_INDEX, 0x0100 );
  602.   //Set the dot clock scanning rate, if applicable
  603.   XSetup_t * pSetup = apSetupTable[ iGraphicsMode ];
  604.   if ( pSetup->iDotClock != 0 ) {
  605.     outp( MISC_OUTPUT, pSetup->iDotClock );
  606.   }
  607.   //Undo reset (restart sequencer)
  608.   outpw( SC_INDEX, 0x0300 );
  609.   //Reprogram the CRT controller.  The VSync End register contains
  610.   //the register write-protect bit, so we save the old value, mask
  611.   //out the write-protect bit, and rewrite the value
  612.   outp( CRTC_INDEX, 0x11 );
  613.   int iTemp = inp( CRTC_INDEX + 1 );
  614.   outp( CRTC_INDEX, 0x11 );
  615.   outp( CRTC_INDEX + 1, iTemp & 0x07f );
  616.   //now that we've removed the write-protection, we reset all the
  617.   //appropriate CRT registers
  618.   for ( int i = 0; i < pSetup->iNumRegisters; ++i ) {
  619.     outpw( CRTC_INDEX, pSetup->aiRegisterValues[ i ] );
  620.   }
  621.   ClearVideoMemory();
  622.   //set screen dimensions
  623.   ScrnPhysicalPixelWidth = pSetup->iWidth;
  624.   SplitScrnScanLine = pSetup->iWidth;
  625.   ScrnPhysicalByteWidth = ScrnPhysicalPixelWidth / 4;
  626.   ScrnPhysicalHeight = pSetup->iHeight;
  627.   //our base X mode is set.  Now reset the logical screen width
  628.   SetLogicalScreenWidth( iNewLogicalWidth );
  629. //  ClearVideoMemory();
  630.   return 0;
  631. }
  632.  
  633. /*
  634. @func Enables Read/Write access to a plane using general memory access
  635. methods.
  636. */
  637. void x_select_default_plane(
  638.   unsigned char bPlane  //@parm Plane to write to
  639. )
  640. {
  641.   bPlane &= 0x03; //mask out so we only have 0-3 to choose from
  642.   int iTemp = 0x0100;
  643.   iTemp <<= bPlane;    //set only the correct bit to 1
  644.   iTemp += MAP_MASK;  //set the map mask
  645.   //Select the write plane
  646.   outpw( SC_INDEX, iTemp );
  647.   //Select the read plane
  648.   iTemp = bPlane << 8;
  649.   iTemp += READ_MAP;
  650.   outpw( GC_INDEX, iTemp );
  651. }
  652.  
  653. /*
  654. @func internal function called to set the split screen scan line,
  655. used by several functions.
  656. */
  657. void _ScanLineBoogie(
  658.   xScreenCoord_t wScanLine
  659. )
  660. {
  661.   //now play with scan line magic
  662.   if ( DoubleScanFlag ) {
  663.     wScanLine *= 2;
  664.     wScanLine -= 1;
  665.   }
  666.   WaitVsyncStart();
  667.   //disable interrupts until the controller is set up
  668.   _disable();
  669.   //output bits 0-7 of the split screen scan line
  670.   outpw( CRTC_INDEX, (( int )wScanLine << 8) + LINE_COMPARE );
  671.   //bit 4 of overflow register == bit 8 of split screen scan line (!?),
  672.  
  673.   //so read the overflow register and set the appropriate bit.
  674.   outp( CRTC_INDEX, OVERFLOW );
  675.   int iPortTemp = inp( CRTC_INDEX + 1 );
  676.   iPortTemp &= ~( 0x10 );   //clear out bit 5
  677.   //now set bit 5 to bit 8 of the split screen scan line
  678.   iPortTemp |= ((( unsigned char )( wScanLine >> 8 )) & 1 ) << 4;
  679.   //and finally output that value to the port.
  680.   outp( CRTC_INDEX + 1, iPortTemp );
  681.   //unfortunately, bit 6 of max scan line register =
  682.   //bit 9 of split screen scan line... here we go again...
  683.   int iTemp = ( (int)wScanLine )& ( 0x02 << 8 );
  684.   iTemp >>= 3; //move bit 9 into bit 6 position
  685.   outp( CRTC_INDEX, MAX_SCAN_LINE );
  686.   iPortTemp = inp( CRTC_INDEX + 1 );
  687.   iPortTemp &= ~( 0x40 ); //clear out bit 6
  688.   iPortTemp |= iTemp;
  689.   outp( CRTC_INDEX, MAX_SCAN_LINE );
  690.   outp( CRTC_INDEX + 1, iPortTemp );
  691.   //enable interrupts again
  692.   _enable();
  693.  
  694. }
  695.  
  696. /*
  697. @func x_set_splitscreen enables the split screen section at the bottom of the
  698. physical screen; good for scores, etc.
  699. */
  700. void x_set_splitscreen(
  701.   xScreenCoord_t wScanLine   //@parm First scan line of the split screen on the display
  702. )
  703. {
  704.   if ( DoubleBufferActive ) {
  705.     ErrorValue = ERROR;
  706.     return;
  707.   }
  708.   if ( SplitScrnActive ) {
  709.     ErrorValue = ERROR;
  710.     return;
  711.   }
  712.   //turn on split screen pel pan suppression so the split screen
  713.   //isn't panned as is the non split screen portion.
  714.   //First reset the AC Index/Data toggle to index state
  715.   int iPortTemp = inp( INPUT_STATUS_0 );
  716.   //Send bit 5 to prevent screen blanking
  717.   outp( AC_INDEX, AC_MODE_CONTROL + 0x20 );
  718.   //get the current AC mode control reg
  719.   iPortTemp = inp( AC_INDEX + 1 );
  720.   //Enable split screen pel panning suppression
  721.   iPortTemp |= 0x20;
  722.   outp( AC_INDEX, iPortTemp );
  723.   //now reset parameters
  724.   PhysicalStartByteX = 0; 
  725.   PhysicalStartPixelX = 0;
  726.   PhysicalStartY = 0;
  727.   SplitScrnActive = TRUE;
  728.   if ( wScanLine < 0 ) {
  729.     wScanLine = 0;
  730.   }
  731.   if ( wScanLine > ScrnPhysicalHeight ) {
  732.     wScanLine = ScrnPhysicalHeight;
  733.   }
  734.   SplitScrnScanLine = wScanLine;
  735.   _ScanLineBoogie( wScanLine );
  736.   SplitScrnVisibleHeight = ScrnPhysicalHeight - SplitScrnScanLine;
  737.   //now set all pages to begin after split screen memory
  738.   Page0_Offs = ScrnLogicalByteWidth * SplitScrnVisibleHeight;
  739.   Page1_Offs = Page0_Offs;
  740.   Page2_Offs = Page0_Offs;
  741.   VisiblePageOffs = HiddenPageOffs = Page0_Offs;
  742.   //calculate # of non-split-screen rows in video ram
  743.   int iNonSplitScreenBytes = 0xffff - Page0_Offs;
  744.   int iNonSplitScreenRows = iNonSplitScreenBytes / ScrnLogicalByteWidth;
  745.   ScrnLogicalHeight = iNonSplitScreenRows;
  746.   if ( BottomClip > ScrnLogicalHeight ) {
  747.     BottomClip = ScrnLogicalHeight;
  748.   }
  749.   MaxScrollY = ScrnLogicalHeight - SplitScrnScanLine;
  750.   x_set_start_addr( 0, 0 );
  751. }
  752.  
  753.  
  754. /*
  755. @func Swaps visible and hidden page offsets and then
  756. executes SetStartAddr to achieve a page flip.  See <f x_set_start_addr>.
  757. */
  758. void x_page_flip(
  759.   xScreenCoord_t wX,  //@parm X coord of new page position
  760.   xScreenCoord_t wY   //@parm Y coord of new page position
  761. )
  762. {
  763.   if ( DoubleBufferActive ) {
  764.     int iTemp = HiddenPageOffs;
  765.     HiddenPageOffs = VisiblePageOffs;
  766.     VisiblePageOffs = iTemp;
  767.     //simulate a XOR
  768.     if ( VisiblePageIdx & 0x01 ) {
  769.       VisiblePageIdx |= ~0x01;
  770.     }
  771.     else {
  772.       VisiblePageIdx |= 0x01;
  773.     }
  774.   }
  775.   if ( TrippleBufferActive ) {
  776.     int iTemp = HiddenPageOffs;
  777.     HiddenPageOffs = VisiblePageOffs;
  778.     VisiblePageOffs = WaitingPageOffs;
  779.     WaitingPageOffs = iTemp;
  780.     ++VisiblePageIdx;
  781.     if ( VisiblePageIdx >= 3 ) {
  782.       VisiblePageIdx = 0;
  783.     }
  784.   }
  785.   x_set_start_addr( wX, wY );
  786. }
  787.  
  788. /*
  789. @func Sets the starting address of the physical visible page
  790. in logical screen memory.
  791. */
  792. void x_set_start_addr(
  793.   xScreenCoord_t wX,   //@parm X coord of new start address
  794.   xScreenCoord_t wY    //@parm Y coord of new start address
  795. )
  796. {
  797.   int iOffset = ScrnLogicalByteWidth * wY;
  798.   if ( DoubleBufferActive || TrippleBufferActive ) {
  799.     iOffset += VisiblePageOffs;
  800.   }
  801.   else {
  802.     iOffset += Page0_Offs;
  803.   }
  804.   PhysicalStartPixelX = wX;
  805.   PhysicalStartY = wY;
  806.   PhysicalStartByteX = wX / 4;
  807.   iOffset += PhysicalStartByteX;
  808.     
  809.   int iLowAddress = ( iOffset << 8 ) + ADDR_LOW;
  810.   int iHighAddress = ( iOffset & ( 0xFF << 8 ) ) + ADDR_HIGH;
  811.   int iPelPanSetup = ( PelPanMask[ wX & 0x03 ] << 8 ) + (PEL_PANNING + 0x20);
  812.   if ( VsyncHandlerActive ) {
  813.     while ( StartAddressFlag ) {
  814.       //do nothing; wait until address flag is clear
  815.     }
  816.     //disable interrupts
  817.     _disable();
  818.     WaitingStartLow = iLowAddress;
  819.     WaitingStartHigh = iHighAddress;
  820.     WaitingPelPan = iPelPanSetup;
  821.     StartAddressFlag = 1;
  822.     //reenable interrupts
  823.     _enable();
  824.     return;
  825.   }
  826.   //wait for trailing edge of vsync pulse
  827.   while ( inp( INPUT_STATUS_0 ) & 0x01 );  
  828.   //now set up the new start address
  829.   _disable();
  830.   outpw( CRTC_INDEX, iLowAddress );
  831.   outpw( CRTC_INDEX, iHighAddress );
  832.   _enable();
  833.   //now wait for vertical sync so the other page will
  834.   //be invisible when we start drawing to it
  835.   while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
  836.   _disable();
  837.   outp( AC_INDEX, iPelPanSetup & 0xff );  //lo byte
  838.   outp( AC_INDEX, iPelPanSetup >> 8 );    //hi byte
  839.   _enable();
  840.   return;
  841. }
  842.  
  843. /*
  844. @func hides the split screen from display.
  845. */
  846. void x_hide_splitscreen(
  847.   void
  848. )
  849. {
  850.   if ( !SplitScrnActive || ( CurrXMode > 4 )) {
  851.     ErrorValue = ERROR;
  852.     return;
  853.   }
  854.   MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight;
  855.   SplitScrnVisibleHeight = 0;
  856.   _ScanLineBoogie( ScrnPhysicalHeight );
  857.   ErrorValue = OK;
  858. }
  859.  
  860. /*
  861. @func shows the split screen at its earlier position.
  862. Only use this if SplitScrnLine hs been set, and do not use in
  863. graphics modes above 4, since it will do nothing.
  864. */
  865. void x_show_splitscreen(
  866.   void
  867. )
  868. {
  869.   if ( !SplitScrnActive || ( CurrXMode > 4 )) {
  870.     ErrorValue = ERROR;
  871.     return;
  872.   }
  873.   MaxScrollY = ScrnLogicalHeight - SplitScrnScanLine;
  874.   SplitScrnVisibleHeight = ScrnPhysicalHeight - SplitScrnScanLine;
  875.   _ScanLineBoogie( SplitScrnScanLine );
  876.   ErrorValue = OK;
  877. }  
  878.  
  879.  
  880. /*
  881. @func Adjusts the split screen scan line to a given value;
  882. only to be used if split screen has been initializes; will not
  883. function for modes above 4.
  884. */
  885. void x_adjust_splitscreen(
  886.   xScreenCoord_t wScanLine    //@parm New scan line to begin displaying split screen
  887. )
  888. {
  889.   if ( !SplitScrnActive ||
  890.     ( CurrXMode > 4 ) ||
  891.     ( wScanLine < SplitScrnScanLine ) ) {
  892.     ErrorValue = ERROR;
  893.     return;
  894.   }
  895.   MaxScrollY = ScrnLogicalHeight - wScanLine;
  896.   SplitScrnVisibleHeight = ScrnPhysicalHeight - wScanLine;
  897.   _ScanLineBoogie( wScanLine );
  898.   ErrorValue = OK;
  899. }
  900.  
  901.  
  902. /*
  903. @func enables double-buffering on the mode X vga memory.
  904. */
  905. int x_set_doublebuffer(
  906.   int wPageHeight    //@parm Height of each page in scan lines
  907. )
  908. {
  909.   if ( DoubleBufferActive ) {
  910.     ErrorValue = ERROR;
  911.     return ERROR;
  912.   }
  913.   //visible page = 0;
  914.   VisiblePageIdx = 0;
  915.   //find if we're requesting a valid page height
  916.   if ( wPageHeight > ( ScrnLogicalHeight / 2 ) ) {
  917.     wPageHeight = ScrnLogicalHeight / 2;
  918.   }
  919.   //set the new logical height
  920.   ScrnLogicalHeight = wPageHeight;
  921.   if ( BottomClip > ScrnLogicalHeight ) {
  922.     BottomClip = ScrnLogicalHeight;
  923.   }
  924.   int iPageSize = ScrnLogicalHeight * ScrnLogicalByteWidth;
  925.   VisiblePageOffs = Page0_Offs;
  926.   Page1_Offs = HiddenPageOffs = Page0_Offs + iPageSize;
  927.   NonVisual_Offs = Page1_Offs + iPageSize;
  928.   DoubleBufferActive = TRUE;
  929.   MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight - SplitScrnVisibleHeight;
  930.   ErrorValue = OK;
  931.   return OK;
  932. }
  933.  
  934.  
  935. /*
  936. @func enables triple-buffering on the mode X vga memory screen.
  937. */
  938. void x_set_tripplebuffer(
  939.   int wPageHeight
  940. )
  941. {
  942.   if ( DoubleBufferActive || TrippleBufferActive ) {
  943.     ErrorValue = ERROR;
  944.     return;
  945.   }
  946.   VisiblePageIdx = 0;
  947.   if ( wPageHeight > ( ScrnLogicalHeight / 3 ) ) {
  948.     wPageHeight = ScrnLogicalHeight / 3;
  949.   }
  950.   ScrnLogicalHeight = wPageHeight;
  951.   if ( BottomClip > ScrnLogicalHeight ) {
  952.     BottomClip = ScrnLogicalHeight;
  953.   }
  954.   int iPageSize = ScrnLogicalHeight * ScrnLogicalByteWidth;
  955.   VisiblePageOffs = Page0_Offs;
  956.   Page1_Offs = HiddenPageOffs = Page0_Offs + iPageSize;
  957.   Page2_Offs = WaitingPageOffs = Page1_Offs + iPageSize;
  958.   NonVisual_Offs = Page2_Offs + iPageSize;
  959.   TrippleBufferActive = TRUE;
  960.  
  961.   MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight - SplitScrnVisibleHeight;
  962.   ErrorValue = OK;
  963. }
  964.  
  965. /*
  966. @func sets the new clipping rectangle for selected clipping functions
  967. */
  968. void x_set_cliprect(
  969.   xScreenCoord_t wLeft,   //@parm left edge of clipping rectangle
  970.   xScreenCoord_t wTop,    //@parm top edge of clipping rectangle
  971.   xScreenCoord_t wRight,  //@parm right edge of clipping rectangle
  972.   xScreenCoord_t wBottom  //@parm bottom edge of clipping rectangle
  973. )
  974. {
  975.   //do x...
  976.   if (wLeft > wRight) {
  977.     int wTemp = wLeft;
  978.     wLeft = wRight;
  979.     wRight = wTemp;
  980.   }
  981.   LeftClip = wLeft;
  982.   RightClip = wRight;
  983.   //...then do y.
  984.   if (wTop > wBottom) {
  985.     int wTemp = wTop;
  986.     wTop = wBottom;
  987.     wBottom = wTemp;
  988.   }
  989.   TopClip = wTop;
  990.   BottomClip = wBottom;
  991. }
  992.  
  993. /*
  994. @func x_text_mode simply returns the user to 80x25 mode
  995. */
  996. void x_text_mode(
  997.   void
  998. )
  999. {
  1000.     ClearVideoMemory();
  1001.     union REGS r;
  1002.     r.x.eax = 0x0003;
  1003.  
  1004.     int386(0x10, &r, &r);
  1005. }
  1006.  
  1007. /*
  1008. @func Waits for the vertical refresh to end
  1009. */
  1010. void x_wait_vsync(
  1011.   void
  1012. )
  1013. {
  1014.   WaitVsyncStart();
  1015. }
  1016.   
  1017.